﻿#include "SysInfoImpl.h"
#include "qregularexpression.h"

#if defined(Q_OS_WIN)

    #include <windows.h>
    SysInfoWindowsImpl::SysInfoWindowsImpl() : SysInfo(),mCpuLoadLastValues()
    {
    }
    double SysInfoWindowsImpl::memoryUsed()
    {
        //获取内存的使用率
        MEMORYSTATUSEX memoryStatus;
        memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
        GlobalMemoryStatusEx(&memoryStatus);
        qulonglong memoryPhysicalUsed = memoryStatus.ullTotalPhys - memoryStatus.ullAvailPhys;
        return (double)memoryPhysicalUsed / (double)memoryStatus.ullTotalPhys * 100.0;
    }
    void SysInfoWindowsImpl::init()
    {
        mCpuLoadLastValues = cpuRawData();
    }
    QVector<qulonglong> SysInfoWindowsImpl::cpuRawData()
    {
        //获取CPU的占用率
        //闲置时间
        FILETIME idleTime;
        //内核使用时间
        FILETIME kernelTime;
        //用户使用时间
        FILETIME userTime;
        GetSystemTimes(&idleTime, &kernelTime, &userTime);
        QVector<qulonglong> rawData;
        rawData.append(convertFileTime(idleTime));
        rawData.append(convertFileTime(kernelTime));
        rawData.append(convertFileTime(userTime));
        return rawData;
    }
    qulonglong SysInfoWindowsImpl::convertFileTime(const FILETIME& filetime) const
    {
        ULARGE_INTEGER largeInteger;
        largeInteger.LowPart = filetime.dwLowDateTime;
        largeInteger.HighPart = filetime.dwHighDateTime;
        return largeInteger.QuadPart;
    }

    double SysInfoWindowsImpl::cpuLoadAverage()
    {
        QVector<qulonglong> firstSample = mCpuLoadLastValues;
        QVector<qulonglong> secondSample = cpuRawData();
        mCpuLoadLastValues = secondSample;

        //获取两个时间点之间的CPU时间
        qulonglong currentIdle = secondSample[0] - firstSample[0];
        qulonglong currentKernel = secondSample[1] - firstSample[1];
        qulonglong currentUser = secondSample[2] - firstSample[2];
        qulonglong currentSystem = currentKernel + currentUser;

        //（总的时间 - 空闲时间）/ 总的时间 = 占用cpu的时间，也就是占用率
        double percent = (currentSystem - currentIdle) * 100.0 / currentSystem ;
        return qBound(0.0, percent, 100.0);
    }
#elif defined(Q_OS_LINUX)

    #include <sys/types.h>
    #include <sys/sysinfo.h>
    #include <QFile>
    #include <QTextStream>

    SysInfoLinuxImpl::SysInfoLinuxImpl() :
        SysInfo(),
        mCpuLoadLastValues()
    {
    }

    void SysInfoLinuxImpl::init()
    {
        mCpuLoadLastValues = cpuRawData();
    }

    double SysInfoLinuxImpl::memoryUsed()
    {
#if 0
        struct sysinfo memInfo;
        sysinfo(&memInfo);
        qulonglong totalMemory = memInfo.totalram;
        totalMemory += memInfo.totalswap;
        totalMemory *= memInfo.mem_unit;
        qulonglong totalMemoryUsed = memInfo.totalram - memInfo.freeram;
        totalMemoryUsed += memInfo.totalswap - memInfo.freeswap;
        totalMemoryUsed *= memInfo.mem_unit;
        double percent = (double)totalMemoryUsed / (double)totalMemory * 100.0;
#elif 1
        double memory;
        double memoryAll;
//        double swap;
//        double swapAll;
        QFile file("/proc/meminfo");
        file.open(QIODevice::ReadOnly | QIODevice::Text);
        QTextStream stream(&file);
        double buff[16] = {0};
        for (int i = 0; i <= 15; ++i) {
            QString line = stream.readLine();
            QStringList list = line.split(QRegularExpression("\\s{1,}"));
            buff[i] = list.at(1).toLong();
        }
        memoryAll = buff[0];
        memory = buff[0] - buff[2];
//        swapAll = buff[14];
//        swap = buff[14] - buff[15];
        double percent = memory * 100.0 / memoryAll;
#endif
        return qBound(0.0, percent, 100.0);
    }

    QVector<qulonglong> SysInfoLinuxImpl::cpuRawData()
    {
        QFile file("/proc/stat");
        file.open(QIODevice::ReadOnly);
        QByteArray line = file.readLine();
        file.close();
        qulonglong totalUser = 0, totalUserNice = 0,
        totalSystem = 0, totalIdle = 0;
        std::sscanf(line.data(), "cpu %llu %llu %llu %llu",
        &totalUser, &totalUserNice, &totalSystem, &totalIdle);
        QVector<qulonglong> rawData;
        rawData.append(totalUser);
        rawData.append(totalUserNice);
        rawData.append(totalSystem);
        rawData.append(totalIdle);
        return rawData;
    }

    double SysInfoLinuxImpl::cpuLoadAverage()
    {
        QVector<qulonglong> firstSample = mCpuLoadLastValues;
        QVector<qulonglong> secondSample = cpuRawData();
        mCpuLoadLastValues = secondSample;
        double overall = (secondSample[0] - firstSample[0])
        + (secondSample[1] - firstSample[1])
        + (secondSample[2] - firstSample[2]);

        //（用户时间 + 系统时间）/ 总的时间 = 占用cpu的时间，也就是占用率
        double total = overall + (secondSample[3] - firstSample[3]);
        double percent = (overall / total) * 100.0;
        return qBound(0.0, percent, 100.0);
    }

#endif
